#ifndef _API_H_
#define _API_H_

#include "rads_base.hpp"

#include <sys/stat.h>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>

#include <ros/ros.h>
#include <ros/time.h>

#include <std_msgs/String.h>
#include <geometry_msgs/PoseStamped.h>
#include <nav_msgs/Path.h>
#include "rads/rads_camera.h"
#include <rads/rads_apis.h>
#include <rads/rads_cmd.h>
#include <rads/rads_acks.h>
#include <rads/rads_trackext.h>
#include <rads/rads_version.h>
#include <rads/rads_versions.h>
#include <fstream>
#include <yaml-cpp/yaml.h>
#include <ros/package.h>  
// json
#include "json.hpp"
using json = nlohmann::json;


// 需要上传的文件模型[这里的code就是指车辆编号vid]
typedef struct
{
    std::string vid;
    std::string mapid;
    std::string code;    // vid
    std::string file;
} API_PcdUpdate;

// 需要上传的文件模型[这里的code就是指车辆编号vid]
typedef struct
{
    std::string id;
    std::string file;
} API_PcdUpdate_img;

// 需要上传的接口数据
typedef struct
{
    // prop
    int map_id;
    int path_id;
    int point_count;
    // lidar
    float x;
    float y;
    float z;
    float yaw;
    float matching_rate;
    // rtk
    float lat;
    float lng;
    float alt;
    float heading;
    int posi_flag;
    int head_flag;
} API_PointUpdate;



// 需要上传的接口数据
typedef struct
{
    std::string device_id;   
    std::string devIp;
    int Alarmtype;
    int preset;
    int preAlarmSum;
    int alarmSum;
    std::string mtAlarmInfo;
    std::string file;
    std::string thermalfile;
} API_Camera;

/// @brief 获取文件大小
/// @param filename :文件
/// @return off_t:文件大小mb
float getFileSize(const std::string &filename)
{
    long len = 0;
    float len_mb = 0;
    struct stat fileStat;
    if (stat(filename.c_str(), &fileStat) != 0)
    {
        return 0;
    }
    len = fileStat.st_size;
    len_mb = len * 0.000001;
    return len_mb;
}

/// @brief 判断是否为pcd后缀文件
/// @param filename :文件 example.txt
/// @param suffix :后缀 .txt
/// @return bool:
bool hasSuffix(const std::string &filename, const std::string &suffix)
{
    size_t len = filename.length();
    size_t suffixLen = suffix.length();
    if (suffixLen > len)
        return false;
    return (strcmp(filename.c_str() + len - suffixLen, suffix.c_str()) == 0);
}


// 上传进度值
std::string ApiPcdRefreshProgress(std::string code, std::string progress)
{
    std::string result = "";
    std::vector<std::string> datas = splitStr(progress,',');
    if (datas.size() == 5)
    {
        std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_TASK_PROGRESS);
        std::string cmd = "curl -X 'GET' '" + url + 
                            "?code=" + code + 
                            "&finishRate=" + datas[0] + 
                            "&remainingTime=" + datas[1] + 
                            "&remainingMileage=" + datas[2] + 
                            "&executeRouteId=" + datas[3] + 
                            "&executeMapId=" + datas[4] + 
                            "' -H 'accept: */*' 2>/dev/null";        
        //std::cout << "ApiPcdRefreshProgress:" << cmd << std::endl;
        FILE *fp;
        char path[1024];
        fp = popen(cmd.c_str(), "r");
        if (fp == NULL)return result;
        while (fgets(path, sizeof(path) - 1, fp) != NULL)
        {
            result += path;
        }
        pclose(fp);
    }
    return result;
}

// 申请建图，下位机就绪状态
std::string ApiPcdCreateReady(int map_id, std::string code)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_MAP_READY_STATE);
    std::string cmd = "curl -X 'GET'  '" + url + "?vMapId=" + std::to_string(map_id) + "&code=" + code + "' -H 'accept: */*'  2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

// PCD文件上传,预通知
std::string ApiPcdUploadNotice(API_PcdUpdate pcd)
{
    float file = getFileSize(pcd.file);
    std::string result = "";
    if (hasSuffix(pcd.file, ".pcd"))
    {
        if ((file- FILE_SIZE_LIMIT) < MINIMUM_VALUE)
        {
            std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_MAP_STATE);
            std::string cmd = "curl -X 'GET'  '" + url + "?vMapId=" + pcd.mapid + "&code=" + pcd.code + "&fileSize=" + std::to_string(file) + "' -H 'accept: */*'  2>/dev/null";
           std::cout << "ApiPcdUploadNotice : "<< cmd << std::endl; 
            FILE *fp;
            char path[1024];
            fp = popen(cmd.c_str(), "r");
            if (fp == NULL)
                return result;
            while (fgets(path, sizeof(path) - 1, fp) != NULL)
            {
                result += path;
            }
            pclose(fp);
        }
    }
    return result;

}


// PCD文件上传，用于建立地图之后
std::string ApiPcdUpload(API_PcdUpdate pcd)
{
    std::string result = "";
    if (hasSuffix(pcd.file, ".pcd"))
    {
        if ((getFileSize(pcd.file) - FILE_SIZE_LIMIT) < MINIMUM_VALUE)
        {
            std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_UPFILE);
            std::string cmd = "curl -X 'POST' '" + url + "' -H 'accept: */*' -H 'Content-Type: multipart/form-data' -F 'vMapId=" + pcd.mapid + "' -F 'code=" + pcd.code + "' -F 'File=@" + pcd.file + "' 2>/dev/null";
            std::cout << "ApiPcdUpload : "<< cmd << std::endl; 
            FILE *fp;
            char path[1024];
            fp = popen(cmd.c_str(), "r");
            if (fp == NULL)
                return result;
            while (fgets(path, sizeof(path) - 1, fp) != NULL)
            {
                result += path;
            }
            pclose(fp);
        }
    }
    return result;
}

// 抓拍img上传
std::string ApiPcdUpload_img(API_PcdUpdate_img img)
{
    std::string result = "";
    
        
            std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_UPFILE_IMG);
            std::string cmd = "curl -X 'POST' '" + url + "' -H 'accept: */*' -H 'Content-Type: multipart/form-data' -F 'id=" + img.id  + "' -F 'File=@" + img.file + "' 2>/dev/null";
            std::cout << "API_PcdUpdate_img : "<< cmd << std::endl; 
            FILE *fp;
            char path[1024];
            fp = popen(cmd.c_str(), "r");
            if (fp == NULL)
                return result;
            while (fgets(path, sizeof(path) - 1, fp) != NULL)
            {
                result += path;
            }
            pclose(fp);
        
    
    return result;
}

std::string ApiCameraUpload(API_Camera img)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_UPFILE_CAMERA);
    
    // Modified command to match Swagger format
    std::string cmd = "curl -X 'POST' '" + url + "' -H 'accept: */*' -H 'Content-Type: multipart/form-data' "
                    "-F 'vehicleCode=" + img.device_id + "' "
                    "-F 'devIp=" + img.devIp + "' "
                    "-F 'alarmType=" + std::to_string(img.Alarmtype) + "' "
                    "-F 'preset=" + std::to_string(img.preset) + "' "
                    "-F 'preAlarmSum=" + std::to_string(img.preAlarmSum) + "' "
                    "-F 'alarmSum=" + std::to_string(img.alarmSum) + "' "
                    "-F 'mtAlarmInfo=" + img.mtAlarmInfo + "' "
                    "-F 'File=@" + img.file + ";type=image/jpeg' "
                    "-F 'thermalFile=@" + img.thermalfile + ";type=image/jpeg' "
                    "2>/dev/null";
    
    std::cout << "ApiCameraUpload : " << cmd << std::endl; 
    
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    
    return result;
}

/// @brief 上报实时的定位数据信息
/// @param point :定位数据信息
/// @return string:服务器端的响应消息
std::string ApiPointUpload(API_PointUpdate point)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_UPPOINT);
    std::string args = "{\
    \"vMapId\": " + std::to_string(point.map_id) + ",\
    \"vRouteId\": " + std::to_string(point.path_id) + ",\
    \"heading\": " + std::to_string(point.heading) + ",\
    \"yaw\": " + std::to_string(point.yaw) + ",\
    \"posiFlag\": " + std::to_string(point.posi_flag) + ",\
    \"headFlag\": " + std::to_string(point.head_flag) + ",\
    \"xvalue\": " + std::to_string(point.x) + ",\
    \"yvalue\": " + std::to_string(point.y) + ",\
    \"zvalue\": " + std::to_string(point.z) + ",\
    \"lat\": " + std::to_string(point.lat) + ",\
    \"lng\": " + std::to_string(point.lng) + ",\
    \"alt\": " + std::to_string(point.alt) + ",\
    \"station\": \"\",\
    \"score\": " + std::to_string(point.matching_rate) + ",\
    \"sort\": " + std::to_string(point.point_count) + "\
    }";
    std::string cmd = "curl -X 'POST' '" + url + "' -H 'accept: */*' -H 'Content-Type: application/json' -d '" + args + "' 2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

/// @brief 下载地图信息
/// @param map_id :地图ID
/// @return string:服务器端的响应消息
std::string ApiPcdDownload(int map_id)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_MAP_DOWN);
    std::string cmd = "curl -X 'GET' '" + url + "?vMapId=" + std::to_string(map_id) + "' -H 'accept: */*'" + " 2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

/// @brief 下载地图
/// @param down_url :地图url
/// @param mapid :地图id
/// @return string:服务器端的响应消息
std::string ApiPcdDown(std::string down_url,std::string mapid)
{
    std::string result = "";
    std::string cmd = "curl -o " + std::string(MAP_PCD_SAVE) + mapid + ".pcd  --progress-bar " + down_url + " 2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

/// @brief 下载线路
/// @param map_id :地图id
/// @param path_id :路径id
/// @return string:服务器端的响应消息
std::string ApipathDown(int map_id,int path_id)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_PATH_DOWN);
    std::string cmd = "curl -X 'GET'  '" + url + "?vMapId=" + std::to_string(map_id) + "&vRouteId=" + std::to_string(path_id) + "'  -H 'accept: */*'" + " 2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

/// @brief 上传轨迹
/// @param data :需要上传的json数据集
/// @return string:服务器端的响应消息
std::string ApiTrajectoryUpload(std::string data)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_PATH_UPLOAD);
    std::string cmd = "curl -X 'POST' '" + url + "' -H 'accept: */*' -H 'Content-Type: application/json' -d '" + data + "' 2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

/// @brief 上传开机点
/// @param data :需要上传的json数据集
/// @return string:服务器端的响应消息
std::string ApiInitPoseUpload(std::string data)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_API_POSE_UPLOAD);
    std::string cmd = "curl -X 'POST' '" + url + "' -H 'accept: */*' -H 'Content-Type: application/json' -d '" + data + "' 2>/dev/null";
    
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

/// @brief 请求版本号
/// @return string:目前服务器上所有版本号的相关信息
std::string ApiVersionGet()
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_RADS_VERSION);
    std::string cmd = "curl -X 'GET'  '" + url + "' -H 'accept: */*'" + " 2>/dev/null";
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}
/// @brief 配置信息
/// @return string:目前服务器上该设备的配置信息的相关信息
std::string ApiDeviceGet(int device_id)
{
    std::string result = "";
    std::string url = std::string(CLOUD_API_URL) + std::string(CLOUD_API_ROUTE) + std::string(CLOUD_RADS_DEVICE);
    std::string cmd = "curl -X 'GET'  '" + url + "/" + std::to_string(device_id) + "'  -H 'accept: */*'" + " 2>/dev/null";
    std::cout << "ApiDeviceGet:" << cmd << std::endl;
    FILE *fp;
    char path[1024];
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
        return result;
    while (fgets(path, sizeof(path) - 1, fp) != NULL)
    {
        result += path;
    }
    pclose(fp);
    return result;
}

#endif